#include "net_server.h"

int get_num_from_serList(const QString ID, QList<server_Struct> List)
{
    for(int i = 0; i < List.count(); i++)
    {
        if(ID == List.at(i).client_Info.ID)
            return i;
    }
    return -1;
}

PUBLIC_FUNCTION_BEGIN

NET_SERVER::NET_SERVER(QObject *parent) :
    QTcpServer(parent)
{
    this->UDPPort = NULL;
}

bool NET_SERVER::start(QString IP, quint16 TCPPort, quint16 UDPPort)
{
    this->TCPPort = TCPPort;
    this->UDPPort = UDPPort;
    if(this->listen(QHostAddress(IP), TCPPort))
    {
        //connect(this, SIGNAL(newConnection()), this, SLOT(newTCPClient()));
        udpSocket = new QUdpSocket;
        if(udpSocket->bind(QHostAddress(IP), UDPPort, QUdpSocket::ShareAddress))
        {
            connect(udpSocket, SIGNAL(readyRead()), this, SLOT(revMSG_UDP()));
        }
    }
    else return false;

    return true;
}

bool NET_SERVER::sendMsg_Udp(UDPenum msgTpye, QByteArray msgData, QHostAddress msgAds, quint16 port)
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_8);
    out <<(quint16)0;
    out << msgTpye;
    if(MSG_ALL_USER_LIST==msgTpye)  //error
    {
        out << msgData;
        out.device()->seek(0);
        out << (quint16)(block.size() - sizeof(quint16));
        foreach(server_Struct i, clientList)
        {
            if(!udpSocket->writeDatagram(block.data(), block.size(), QHostAddress(i.UDPIP), (quint16)i.UDPPort))
                return false;
        }
        return true;
    }
    else if(MSG_CLIENT_BROADCAST_INFO==msgTpye || MSG_SERVER_BROADCAST_INFO==msgTpye)
    {
        out << msgData;
        out.device()->seek(0);
        out << (quint16)(block.size() - sizeof(quint16));
        foreach(server_Struct i, clientList)
        {
            if(!udpSocket->writeDatagram(block.data(), block.size(), QHostAddress(i.UDPIP), (quint16)i.UDPPort))
                return false;
        }
        emit send_broadcast(msgData);
        return true;
    }
    else if(MSG_CLINET_LOGIN_SUCCESS == msgTpye)
    {
        if(msgData.count() > 0)
        {
            QStringList tempList;
            tempList.append(msgData);
            tempList.append(msgAds.toString());
            out << tempList;
        }
        out.device()->seek(0);
        out << (quint16)(block.size() - sizeof(quint16));
        if(udpSocket->writeDatagram(block.data(), block.size(), msgAds, (quint16)port))
            return true;
    }
    else if(MSG_CLIENT_CHAT == msgTpye)
    {
        out << msgData;
        out.device()->seek(0);
        out << (quint16)(block.size() - sizeof(quint16));
        if(udpSocket->writeDatagram(block.data(), block.size(), msgAds, (quint16)port))
            return true;
    }
    return false;
}

PUBLIC_FUNCTION_END

void NET_SERVER::incomingConnection(int socketDescriptor)
{
    tcpSocThread *tcp_Thread = new tcpSocThread(socketDescriptor, this);
    connect(tcp_Thread, SIGNAL(readyClient_Struct(client_Struct)), this, SLOT(getClient_Struct(client_Struct)));
    connect(tcp_Thread, SIGNAL(logout(QString)), this, SLOT(on_logout(QString)));
    connect(tcp_Thread, SIGNAL(finished()), this, SLOT(deleteLater()));
    tcpconnectList.append(tcp_Thread);
    tcp_Thread->start();
}

void NET_SERVER::on_logout(QString name)
{
    for(int i = 0; i < clientList.count(); i++)
    {
        if(name == clientList.at(i).client_Info.ID)
        {
            clientList.removeAt(i);
            break;
        }
    }

    usersListUpdate_client();
    usersListUpdate(clientList);
}

void NET_SERVER::revMSG_UDP()
{
    QByteArray block;
    QHostAddress udp_IP;
    quint16 udp_Port;
    while(udpSocket->hasPendingDatagrams())
    {
        block.resize(udpSocket->pendingDatagramSize());
        if(-1 == udpSocket->readDatagram(block.data(), block.size(), &udp_IP, &udp_Port))
            continue;
    }
    deMsg_UDP(block, udp_IP.toString(), udp_Port);
}

void NET_SERVER::deMsg_UDP(QByteArray msg_UDP, QString IP, quint16 Port)
{
    QDataStream in(&msg_UDP, QIODevice::ReadOnly);
    in.setVersion(QDataStream::Qt_4_8);
    quint16 dataGramSize;
    quint32 udp_msg_num;
    UDPenum udp_msg;
    in >> dataGramSize >> udp_msg_num;
    udp_msg = (enum UDPenum)udp_msg_num;

/*    switch(udp_msg)
    {
    case MSG_ALL_USER_LIST :
        break;
    case MSG_CLIENT_MAC :
        QByteArray msgData;
        in >> msgData;
        int num = get_num_from_serList(msgData, clientList);
        clientList.at(num).UDPIP = IP;
        clientList.at(num).UDPPort = Port;
        break;
    case MSG_CLIENT_BROADCAST_INFO :
        QByteArray msgData;
        in >> msgData;
        sendMsg_Udp(MSG_CLIENT_BROADCAST_INFO, msgData);
        break;
    case MSG_CLIENT_CHAT :
        QStringList msgData;
        in >> msgData;
        sendMsg_Udp(MSG_CLIENT_CHAT, msgData.at(1).toLatin1(), QHostAddress(msgData[0]));
        break;
    case MSG_CLINET_LOGOUT :
        break;
    default :
        break;
    }*/

    if(MSG_CLIENT_MAC == udp_msg)
    {
        QStringList msgData;
        in >> msgData;
        server_Struct tempSer;
        tempSer.client_Info.ID = msgData[0];
        tempSer.client_Info.IP = msgData[1];
        tempSer.UDPIP = IP;
        tempSer.UDPPort = Port;
        getClient_Struct(tempSer);
        /*int num = get_num_from_serList(msgData, clientList);
        //if(num >= 0)
        //{
        //    clientList[num].UDPIP = IP;
        //    clientList[num].UDPPort = Port;
        //}*/
    }
    else if(MSG_CLIENT_BROADCAST_INFO == udp_msg)
    {
        QByteArray msgData;
        in >> msgData;
        sendMsg_Udp(MSG_CLIENT_BROADCAST_INFO, msgData);
    }
    else if(MSG_CLIENT_CHAT == udp_msg)
    {
        QStringList msgData;
        in >> msgData;
        int num = get_num_from_serList(msgData[0], clientList);
        QByteArray sendmsg;
        QDataStream out(&sendmsg, QIODevice::WriteOnly);
        out.setVersion(QDataStream::Qt_4_8);
        out << msgData.mid(1);
        sendMsg_Udp(MSG_CLIENT_CHAT, sendmsg, QHostAddress(clientList.at(num).UDPIP), clientList.at(num).UDPPort);
    }
    else if(MSG_CLIENT_BRC == udp_msg)
    {
        QByteArray msgData;
        in >> msgData;
        foreach(server_Struct i, clientList)
        {
            if(i.client_Info.ID == msgData)
            {
                i.UDPIP = IP;
                i.UDPPort = Port;
            }
        }
    }
/*    else if(MSG_CLINET_LOGIN_SUCCESS == udp_msg)
    {
        sendMsg_Udp(MSG_CLINET_LOGIN_SUCCESS, "", IP, Port);
    }*/
}

void NET_SERVER::getClient_Struct(server_Struct client)
{
    foreach(server_Struct i, clientList)
    {
        if( i.client_Info.ID == client.client_Info.ID && i.client_Info.IP == client.client_Info.IP)
        {
            sendMsg_Udp(MSG_CLIENT_LOGIN_FAIL);
            return ;
        }
    }

    sendMsg_Udp(MSG_CLINET_LOGIN_SUCCESS, "", QHostAddress(client.UDPIP), client.UDPPort);

    //delay 500ms
    QDateTime n2=QDateTime::currentDateTime();
    QDateTime now;
    do{
        now=QDateTime::currentDateTime();
    } while(n2.msecsTo(now) <= 500);

    clientList.append(client);

    usersListUpdate_client();

    emit usersListUpdate(clientList);
}

void NET_SERVER::usersListUpdate_client()
{
    QByteArray tempByte;
    QDataStream out(&tempByte, QIODevice::WriteOnly);
    foreach(server_Struct i, clientList)
    {
        QStringList tempStrList;
        tempStrList.append(i.client_Info.ID);
        tempStrList.append(i.client_Info.IP);
        //tempStrList.append(QString::number(i.Port));
        out << tempStrList;
    }
    sendMsg_Udp(MSG_ALL_USER_LIST, tempByte);
}
